package com.ruoyi.business.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.business.Dto.GrowDto;
import com.ruoyi.business.common.CommonValues;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.mapper.BusStudentGrowthItemMapper;
import com.ruoyi.business.mapper.BusStudentGrowthMapper;
import com.ruoyi.business.mapper.BusUserCommentsMapper;
import com.ruoyi.business.service.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.framework.web.exception.MyException;
import com.ruoyi.system.common.RedisKeyPrefix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 学生成长报告项Service业务层处理
 *
 */
@Service
public class BusStudentGrowthItemServiceImpl extends ServiceImpl<BusStudentGrowthItemMapper,BusStudentGrowthItem> implements IBusStudentGrowthItemService
{
    @Autowired
    private BusStudentGrowthItemMapper busStudentGrowthItemMapper;

    //班级学生表
    @Autowired
    private IBusGradeStudentService busGradeStudentService;
    //学生表
    @Autowired
    private IBusStudentsService busStudentsService;
    //学习成长报告表
    @Autowired
    private IBusStudentGrowthService busStudentGrowthService;
    //学习成长报告项表
    @Autowired
    private IBusStudentGrowthItemService busStudentGrowthItemService;
    @Autowired
    private BusUserCommentsMapper commentsMapper;
    @Autowired
    private IBusSemesterService busSemesterService;

    @Autowired
    private BusStudentGrowthMapper growthMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IBusUserSealService sealService;

    //存储天数
    @Value("${store-time}")
    private Long storeDays;

    private final List<String> itemNames = Arrays.asList(CommonValues.ITEMS);
    /**
     * 查询学生成长报告项
     * @param growth 学生成长报告项主键
     * @return 学生成长报告项
     */

    @Override
    public Map<String,Object> selectBusStudentGrowthItemByGrowthId(BusStudentGrowth growth) {
        List<BusGrowthItemDto> busStudentGrowthItems = busStudentGrowthItemMapper.
                selectBusStudentGrowthItemByGrowthId(growth);
        HashMap<String, Object> map = new HashMap<>();
        busStudentGrowthItems.forEach((item)->{
            JSONObject entries = new JSONObject();
            if (StringUtils.isNotEmpty(item.getValue())){
                entries = JSONUtil.parseObj(item.getValue());
            }
            entries.putOnce("status",item.getStatus());
            map.put(item.getKey(), entries);
        });
        return map;
    }
    @Override
    public Map<String, Object> getInfo(BusStudentGrowth growth){
        //先尝试从redis中获取(service对应的接口需在存redis中使用,所以取操作放在controller)
        Map<Object, Object> entries = redisTemplate.opsForHash().entries("growth:" + growth.getGrowthId());
        Map<String, Object> result = new HashMap<>();
        List<BusCommonSeal> commonSeals = sealService.getCommonSeals();
        HashMap<String, String> sealMap = new HashMap<>();
        commonSeals.forEach((seal)->{
            sealMap.put(seal.getSealName(),seal.getSealUrl());
        });
        result.put("seals",sealMap);
        if (entries.isEmpty()){
            Map<String, Object> entriesBySql = busStudentGrowthItemService.
                    selectBusStudentGrowthItemByGrowthId(growth);
            Set<String> keys = entriesBySql.keySet();
            for (String o : keys) {
                String index = String.valueOf(itemNames.indexOf(o));
                result.put(index,new JSONObject(entriesBySql.get(o)));
            }
        }else{
            Set<Object> keys = entries.keySet();
            for (Object o : keys) {
                String index = String.valueOf(itemNames.indexOf(o.toString()));
                result.put(index,new JSONObject(entries.get(o)));
            }
        }
        return result;
    }

    /**
     * 用来统计未完成人数名单
     * @param gradeId
     * @param semesterId
     * @return
     */
    @Override
    public List<Map<String,List<String>>> getGrowthStudentName(Long gradeId,Long semesterId) {
        GrowDto growDto=new GrowDto();
        //用来统计这个班级学习模块未完成的名单
        Map<String, List<String>> mapModulePace = growDto.getMapName();
        //用来统计这个班级完成、进行中、未完成的学生名单
        Map<String, List<String>> mapNameCount = growDto.getMapNameCount();
        List<Map<String,List<String>>> StudentNameInfo =new ArrayList<>();
        //拿到这个班级所对应的学生对象
        LambdaQueryWrapper<BusGradeStudent> gradeStudentWrapper=new LambdaQueryWrapper<>();
        gradeStudentWrapper.eq(BusGradeStudent::getGradeId,gradeId);
        List<BusGradeStudent> gradeStudents = busGradeStudentService.list(gradeStudentWrapper);
        //历遍这个班级的所有的学生
        for (BusGradeStudent student:gradeStudents) {
            Long studentId = student.getStudentId();
            //拿到这个学生的信息表
            LambdaQueryWrapper<BusStudents> busStudentsWrapper=new LambdaQueryWrapper<>();
            busStudentsWrapper.eq(BusStudents::getStuId,studentId);
            BusStudents studentInfo = busStudentsService.
                    getOne(busStudentsWrapper);
            //再拿到这个学生的成长报告表
            LambdaQueryWrapper<BusStudentGrowth> busStudentGrowthWrapper=new LambdaQueryWrapper<>();
            busStudentGrowthWrapper.eq(BusStudentGrowth::getStudentId,studentInfo.getStuId());
            //再嵌入学期条件
            busStudentGrowthWrapper.eq(BusStudentGrowth::getSemesterId,semesterId);
            BusStudentGrowth studentGrowth = busStudentGrowthService.getOne(busStudentGrowthWrapper);

            //拿到属于这个学生的成长项表的Id
            Long growthId = studentGrowth.getGrowthId();
            //查这个项表的各个参数再进行封装

            //先拿到这个学生的项表
            LambdaQueryWrapper<BusStudentGrowthItem> busStudentGrowthItemWrapper=new LambdaQueryWrapper<>();
            busStudentGrowthItemWrapper.eq(BusStudentGrowthItem::getGrowthId,growthId);

            //拿到这个学生各个模块的对象集合，按理来说应该是多少个模块就有多少个对象
            List<BusStudentGrowthItem> growthItems = busStudentGrowthItemService.list(busStudentGrowthItemWrapper);

            //用于模块完成的统计
            int count=0;
            //对该学生的模块进行封装
            for (BusStudentGrowthItem growthItem: growthItems) {
                //拿到这个学生的模块key
                String growthKey = growthItem.getGrowthKey();
                //再拿到它这个模块的填写状态,true就是以填写
                Boolean status = growthItem.getStatus().equals("1");
                if (status){
                    count++;
                    //拿到这个学生未完成的模块以后，对其进行录入
                    List<String> StudentName = mapModulePace.get(growthKey);
                    StudentName.add(studentInfo.getStuName());
                    //再将模块未完成的人重新封装回mapName
                    mapModulePace.put(growthKey,StudentName);
                }
            }
            String flag;
            if (count==0){
                flag="未开始";
            }else if (count==growthItems.size()){
                flag="已完成";
            }else {
                flag="进行中";
            }
            List<String> list = mapNameCount.get(flag);
            list.add(studentInfo.getStuName());
            mapNameCount.put(flag,list);
        }
        StudentNameInfo.add(mapModulePace);
        StudentNameInfo.add(mapNameCount);
        return StudentNameInfo;
    }

    @Override
    public List<Map<String, List<String>>> getGrowthNotVerifyStudentName(Long gradeId, Long semesterId) {
        GrowDto growDto=new GrowDto();
        //用来统计这个班级学习模块未完成的名单
        Map<String, List<String>> mapModulePace = growDto.getMapName();
        //用来统计这个班级完成、进行中、未完成的学生名单
        Map<String, List<String>> mapNameCount = growDto.getMapNameCount();
        List<Map<String,List<String>>> StudentNameInfo =new ArrayList<>();
        //拿到这个班级所对应的学生对象
        LambdaQueryWrapper<BusGradeStudent> gradeStudentWrapper=new LambdaQueryWrapper<>();
        gradeStudentWrapper.eq(BusGradeStudent::getGradeId,gradeId);
        List<BusGradeStudent> gradeStudents = busGradeStudentService.list(gradeStudentWrapper);
        //历遍这个班级的所有的学生
        for (BusGradeStudent student:gradeStudents) {
            Long studentId = student.getStudentId();
            //拿到这个学生的信息表
            LambdaQueryWrapper<BusStudents> busStudentsWrapper=new LambdaQueryWrapper<>();
            busStudentsWrapper.eq(BusStudents::getStuId,studentId);
            BusStudents studentInfo = busStudentsService.
                    getOne(busStudentsWrapper);
            //再拿到这个学生的成长报告表
            LambdaQueryWrapper<BusStudentGrowth> busStudentGrowthWrapper=new LambdaQueryWrapper<>();
            busStudentGrowthWrapper.eq(BusStudentGrowth::getStudentId,studentInfo.getStuId());
            //再嵌入学期条件
            busStudentGrowthWrapper.eq(BusStudentGrowth::getSemesterId,semesterId);
            BusStudentGrowth studentGrowth = busStudentGrowthService.getOne(busStudentGrowthWrapper);

            //拿到属于这个学生的成长项表的Id
            Long growthId = studentGrowth.getGrowthId();
            //查这个项表的各个参数再进行封装

            //先拿到这个学生的项表
            LambdaQueryWrapper<BusStudentGrowthItem> busStudentGrowthItemWrapper=new LambdaQueryWrapper<>();
            busStudentGrowthItemWrapper.eq(BusStudentGrowthItem::getGrowthId,growthId);

            //拿到这个学生各个模块的对象集合，按理来说应该是多少个模块就有多少个对象
            List<BusStudentGrowthItem> growthItems = busStudentGrowthItemService.list(busStudentGrowthItemWrapper);

            //用于模块完成的统计
            int count=0;
            //对该学生的模块进行封装
            for (BusStudentGrowthItem growthItem: growthItems) {
                //拿到这个学生的模块key
                String growthKey = growthItem.getGrowthKey();
                //再拿到它这个模块的填写状态,true就是以填写
                Boolean status = growthItem.getStatus().equals("0");
                if (status){
                    count++;
                    //拿到这个学生未完成的模块以后，对其进行录入
                    List<String> StudentName = mapModulePace.get(growthKey);
                    StudentName.add(studentInfo.getStuName());
                    //再将模块未完成的人重新封装回mapName
                    mapModulePace.put(growthKey,StudentName);
                }
            }
            String flag;
            if (count==0){
                flag="已完成";
            }else if (count==growthItems.size()){
                flag="未开始";
            }else {
                flag="进行中";
            }
            List<String> list = mapNameCount.get(flag);
            list.add(studentInfo.getStuName());
            mapNameCount.put(flag,list);
        }
        StudentNameInfo.add(mapModulePace);
        StudentNameInfo.add(mapNameCount);
        return StudentNameInfo;

    }


    /**
     * 新增学生成长报告项
     *
     * @param busStudentGrowthItem 学生成长报告项
     * @return 结果
     */
    @Override
    public int insertBusStudentGrowthItem(BusStudentGrowthItem busStudentGrowthItem)
    {
        return busStudentGrowthItemMapper.insertBusStudentGrowthItem(busStudentGrowthItem);
    }

    /**
     * 修改学生成长报告项
     * 
     * @param busStudentGrowthItem 学生成长报告项
     * @return 结果
     */
    @Override
    public int updateBusStudentGrowthItem(BusStudentGrowthItem busStudentGrowthItem)
    {
        return busStudentGrowthItemMapper.updateBusStudentGrowthItem(busStudentGrowthItem);
    }



    /**
     * 删除学生成长报告项信息
     * 
     * @param growthItemId 学生成长报告项主键
     * @return 结果
     */
    @Override
    public int deleteBusStudentGrowthItemByGrowthItemId(Long growthItemId)
    {
        return busStudentGrowthItemMapper.deleteBusStudentGrowthItemByGrowthItemId(growthItemId);
    }
    /**
     *
     */
    @Override
    public void insertComments(BusUserComments busUserComments){
        //查询班主任和任课老师的寄语
        List<BusUserComments> comments = commentsMapper.
                getAllComments(busUserComments);
        //获取学生当前学期的growthId
        Long growthId = getCurrentGrowthId(busUserComments.getStudentId());
        //根据环节名和growthId锁定记录获取
        BusStudentGrowthItem busStudentGrowthItem = new BusStudentGrowthItem();
        busStudentGrowthItem.setGrowthId(growthId);
        busStudentGrowthItem.setGrowthKey("教师寄语");
        busStudentGrowthItem.setStatus("1");
        JSONObject entries = new JSONObject();
        //取出班主任和任课教师寄语封装为json
        comments.forEach((comment)->{
            if (comment.getRemark().equals("0")){
                entries.set("班主任寄语",comment.getComments());
                entries.set("seal1",sealService.getSealByUserId(comment.getUserId()));
            }else {
                entries.set("教师寄语",comment.getComments());
                entries.set("seal2",sealService.getSealByUserId(comment.getUserId()));
            }
        });
        busStudentGrowthItem.setGrowthValue(entries.toString());
        busStudentGrowthItemMapper.
                updateBusStudentGrowthItem(busStudentGrowthItem);
    }
    @Override
    public Long getCurrentGrowthId(Long studentId){
        return growthMapper.getStudentCurrentGrowthId(studentId,
                busSemesterService.getCurrentSemesterId());
    }
    /**制作成长报告上传图片 */
    @Override
    public int uploadImg(MultipartFile file, BusStudentGrowthItem busStudentGrowthItem) throws IOException, InvalidExtensionException, InterruptedException {
        String path = FileUploadUtils.upload(RuoYiConfig.getGrowthPath(),
                file, MimeTypeUtils.IMAGE_EXTENSION);
        busStudentGrowthItem.setGrowthValue(path);
        return uploadCommonMethod(busStudentGrowthItem);
    }

    @Override
    public int uploadImg(BusStudentGrowthItem busStudentGrowthItem) throws InterruptedException {
        return uploadCommonMethod(busStudentGrowthItem);
    }
    public int uploadCommonMethod(BusStudentGrowthItem busStudentGrowthItem) throws InterruptedException {
        stringRedisTemplate.delete("growth:"+busStudentGrowthItem
                .getGrowthId());
        busStudentGrowthItem.setStatus("1");
        //防止同时上传多张图片出现线程安全问题,使用redis对其进行上锁
        while (StringUtils.isNotEmpty(stringRedisTemplate.opsForValue().get(
                RedisKeyPrefix.GROWTH_ITEM_WRITE_NOW+
                        busStudentGrowthItem.getGrowthId()))){
            Thread.sleep(1000);
        };
        stringRedisTemplate.opsForValue().set(
                RedisKeyPrefix.GROWTH_ITEM_WRITE_NOW+
                        busStudentGrowthItem.getGrowthId(),"1",5,TimeUnit.SECONDS);
        //先查询该item的value应对一个value对应多张图片情况
        String itemValueByKeyAndGrowthId = busStudentGrowthItemMapper.
                getItemValueByKeyAndGrowthId(busStudentGrowthItem);
        JSONObject values;
        if (StringUtils.isNotEmpty(itemValueByKeyAndGrowthId)){
            values = new JSONObject(itemValueByKeyAndGrowthId);
        }else{
            values = new JSONObject();
        }
        //将图片名存入item表中
        values.set("img"+busStudentGrowthItem.getRemark(),
                busStudentGrowthItem.getGrowthValue());
        busStudentGrowthItem.setGrowthValue(values.toString());
        int result = busStudentGrowthItemMapper
                .updateBusStudentGrowthItem(busStudentGrowthItem);
        stringRedisTemplate.delete(
                RedisKeyPrefix.GROWTH_ITEM_WRITE_NOW+
                        busStudentGrowthItem.getGrowthId());
        return result;
    }

    @Override
    public void storeGrowthItems(Long growthId,Map<String,Object> items) {
        for (String s : items.keySet()) {
            Object o = items.get(s);
            items.put(s,o.toString());
        }
        stringRedisTemplate.opsForHash().putAll("growth:"+growthId,items);
        stringRedisTemplate.expire("growth:"+growthId,storeDays,
                TimeUnit.DAYS);
    }

    @Override
    public List<JSONObject> getHistoryItems(Long studentId,String itemKey) {
        List<String> growthResByStudentId = busStudentGrowthService.getGrowthResByStudentId(studentId, itemKey);
        List<JSONObject> jsonGrowth = new ArrayList<>();
        growthResByStudentId.forEach((item)->{
            if (StringUtils.isNotEmpty(item)){
                String index = String.valueOf(itemNames.indexOf(itemKey));
                jsonGrowth.add(new JSONObject(new JSONObject(item).get(index)));
            }
        });
        return jsonGrowth;
    }

    @Override
    public Date getEndTime() {
        Long currentSemesterId = busSemesterService.getCurrentSemesterId();
        Date endTime;
        endTime = (Date)redisTemplate.opsForValue()
                .get(RedisKeyPrefix.CURRENT_REPORT_FINISH_TIME);
        if (endTime == null){
            endTime = busStudentGrowthItemMapper.getEndTime(currentSemesterId);
            redisTemplate.opsForValue()
                    .set(RedisKeyPrefix.CURRENT_REPORT_FINISH_TIME+currentSemesterId,
                            endTime,3,TimeUnit.DAYS);
        }
        return endTime;
    }

    @Override
    public void updateStatus(Long growthId) {
         busStudentGrowthItemMapper.updateStatus(growthId);
    }
    //清空growth_item表,将其存入growth表中growth_result字段,在增加学期中被调用
    @Override
    public void moveGrowthItem() {
        //获取当前学期的所有growthId
        Long currentSemesterId = busSemesterService.getCurrentSemesterId();
        List<Long> activeId = growthMapper.
                getActiveId(currentSemesterId);
        if (activeId.isEmpty()){
            return;
        }
        activeId.forEach((id)->{
            BusStudentGrowth busStudentGrowth = new BusStudentGrowth();
            busStudentGrowth.setGrowthId(id);
            Map<String, Object> info = getInfo(busStudentGrowth);
            JSONObject entries = new JSONObject(info);
            busStudentGrowthItemMapper.clearItem(id);
            for (String s : entries.keySet()) {
                if(entries.get(s) == null){
                    entries.set(s,"");
                }
            }

            //放入growth表中
            growthMapper.setResult(id,entries.toString());
        });
    }
}
